/***************************************************************************//**
 * @file HID/HID_Controls.h
 * @author  Marek M. Cel <marekcel@mscsim.org>
 *
 * @section LICENSE
 *
 * Copyright (C) 2013 Marek M. Cel
 *
 * This file is part of MScSim. You can redistribute and modify it under
 * the terms of GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Further information about the GNU General Public License can also be found
 * on the world wide web at http://www.gnu.org.
 ******************************************************************************/
#ifndef HID_CONTROLS_H
#define HID_CONTROLS_H

////////////////////////////////////////////////////////////////////////////////

#include "HID_Joysticks.h"

////////////////////////////////////////////////////////////////////////////////

#define MSCSIM_HID_ACTIONS 53
#define MSCSIM_HID_ENGINES 4

////////////////////////////////////////////////////////////////////////////////

/** Controls class. */
class HID_Controls
{
public:

    /** */
    enum AssignemtTypes
    {
        None = 0,               ///< (0)
        Keyboard,               ///< (1)
        Joystick                ///< (2)
    };

    /** */
    enum ActionsTypes
    {
        RollAxis = 0,           ///< (0)  Roll (Axis)
        RollBankLeft,           ///< (1)  Roll: Bank Left
        RollBankRight,          ///< (2)  Roll: Bank Right
        PitchAxis,              ///< (3)  Pitch (Axis)
        PitchNoseUp,            ///< (4)  Pitch: Nose Up
        PitchNoseDown,          ///< (5)  Pitch: Nose Down
        YawAxis,                ///< (6)  Yaw (Axis)
        YawTurnLeft,            ///< (7)  Yaw: Turn Left
        YawTurnRight,           ///< (8)  Yaw: Turn Right
        TrimRollAxis,           ///< (9)  Trim Roll (Axis)
        TrimRollBankLeft,       ///< (10) Trim Roll: Bank Left
        TrimRollBankRight,      ///< (11) Trim Roll: Bank Right
        TrimPitchAxis,          ///< (12) Trim Pitch (Axis)
        TrimPitchNoseUp,        ///< (13) Trim Pitch: Nose Up
        TrimPitchNoseDown,      ///< (14) Trim Pitch: Nose Down
        TrimYawAxis,            ///< (15) Trim Yaw (Axis)
        TrimYawTurnLeft,        ///< (16) Trim Yaw: Turn Left
        TrimYawTurnRight,       ///< (17) Trim Yaw: Turn Right
        BrakeLeftAxis,          ///< (18) Wheel Brake Left (Axis)
        BrakeLeftApply,         ///< (19) Wheel Brake Left: Apply
        BrakeRightAxis,         ///< (20) Wheel Brake Right (Axis)
        BrakeRightApply,        ///< (21) Wheel Brake Right: Apply
        ParkingBrakeApply,      ///< (22) Parking Brake: Apply
        ParkingBrakeRelease,    ///< (23) Parking Brake: Release
        LandingGearExtend,      ///< (24) Landing Gear: Extend
        LandingGearRelease,     ///< (25) Landing Gear: Retract
        FlapsExtend,            ///< (26) Flaps: Extend
        FlapsRetract,           ///< (27) Flaps: Retract
        AirbrakeExtend,         ///< (28) Airbrake: Extend
        AirbrakeRetract,        ///< (29) Airbrake: Retract
        SpoilersExtend,         ///< (30) Spoilers: Extend
        SpoilersRetract,        ///< (31) Spoilers: Retract
        CollectiveAxis,         ///< (32) Collective (Axis)
        CollectiveIncrease,     ///< (33) Collective: Increase
        CollectiveDecreade,     ///< (34) Collective: Decrease
        ThrottleAxis1,          ///< (35) Throttle 1 (Axis)
        ThrottleAxis2,          ///< (36) Throttle 2 (Axis)
        ThrottleAxis3,          ///< (37) Throttle 3 (Axis)
        ThrottleAxis4,          ///< (38) Throttle 4 (Axis)
        ThrottleIncrease,       ///< (39) Throttle: Increase
        ThrottleDecrease,       ///< (40) Throttle: Decrease
        MixtureAxis1,           ///< (41) Mixture 1 (Axis)
        MixtureAxis2,           ///< (42) Mixture 2 (Axis)
        MixtureAxis3,           ///< (43) Mixture 3 (Axis)
        MixtureAxis4,           ///< (44) Mixture 4 (Axis)
        MixtureAxisRich,        ///< (45) Mixture: Rich
        MixtureAxisLean,        ///< (46) Mixture: Lean
        PropellerAxis1,         ///< (47) Propeller 1 (Axis)
        PropellerAxis2,         ///< (48) Propeller 2 (Axis)
        PropellerAxis3,         ///< (49) Propeller 3 (Axis)
        PropellerAxis4,         ///< (50) Propeller 4 (Axis)
        PropellerIncrease,      ///< (51) Propeller: Increase
        PropellerDecrease       ///< (52) Propeller: Decrease
    };

    /** */
    struct Action
    {
        int assignment;     ///<
        
        int keyId;          ///<
        
        int joystickId;     ///<
        int axisId;         ///<
        int buttonId;       ///<
        int inverted;       ///<
    };

    /** Constructor. */
    HID_Controls();

    /** Destructor. */
    virtual ~HID_Controls();

    /** */
    void init( void *winId );

    /** */
    void update( double timeStep );

private:

    Action m_actions[ MSCSIM_HID_ACTIONS ]; ///<

    float m_timeStep;           ///< [s] simulation time step

    float m_speedCtrl;          ///< [1/s]
    float m_speedTrim;          ///< [1/s]
    float m_speedBrakes;        ///< [1/s]
    float m_speedGear;          ///< [1/s]
    float m_speedFlaps;         ///< [1/s]
    float m_speedAirbrake;      ///< [1/s]
    float m_speedSpoilers;      ///< [1/s]
    float m_speedThrottle;      ///< [1/s]
    float m_speedMixture;       ///< [1/s]
    float m_speedPropeller;     ///< [1/s]

    float m_ctrlRoll;           ///< -1.0 ... 1.0
    float m_ctrlPitch;          ///< -1.0 ... 1.0
    float m_ctrlYaw;            ///< -1.0 ... 1.0

    float m_trimRoll;           ///< -1.0 ... 1.0
    float m_trimPitch;          ///< -1.0 ... 1.0
    float m_trimYaw;            ///< -1.0 ... 1.0

    float m_brakeLeft;          ///< 0.0 ... 1.0
    float m_brakeRight;         ///< 0.0 ... 1.0

    float m_commonGear;         ///<

    float m_gear[ 3 ];          ///< 0.0 ... 1.0

    float m_flaps;              ///< 0.0 ... 1.0
    float m_airbrake;           ///< 0.0 ... 1.0
    float m_spoilers;           ///< 0.0 ... 1.0

    float m_collective;         ///< 0.0 ... 1.0

    float m_commonThrottle;     ///< 0.0 ... 1.0
    float m_commonMixture;      ///< 0.0 ... 1.0
    float m_commonPropeller;    ///< 0.0 ... 1.0

    float m_throttles  [ MSCSIM_HID_ENGINES ];  ///< 0.0 ... 1.0
    float m_mixtures   [ MSCSIM_HID_ENGINES ];  ///< 0.0 ... 1.0
    float m_propellers [ MSCSIM_HID_ENGINES ];  ///< 0.0 ... 1.0

    int m_parkingBrake;         ///< specifies if parking brakes are applied
    int m_landingGear;          ///< specifies if landing gear is extended

    /** Using this constructor is forbidden. */
    HID_Controls( const HID_Controls & ) {}

    /** */
    void getJoyAxisValue( const Action &action, float &value, int absolute = 0 );
    
    /** */
    void getKeyAxisValue( int decreaseAction,
                          int increaseAction,
                          float &value,
                          float speed,
                          float min,
                          float max );
    
    /** */
    void getJoyButtState( const Action &action, int &state );

    /** */
    void reset();

    /** */
    void updateAxisActions();
    
    /** */
    void updateNonAxisActions();
};

////////////////////////////////////////////////////////////////////////////////

#endif // HID_CONTROLS_H
